﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using OpenExpressApp.MetaAttribute;
using System.Reflection;
using System.Collections;
using OpenExpressApp.Command;
using OpenExpressApp.Types;
using System.Diagnostics;
using OpenExpressApp.MetaModel;
using System.Windows.Media;
using Csla;

namespace OpenExpressApp
{
    [Serializable]
    public class BusinessObjectInfoList : GBusinessListBase<BusinessObjectInfoList, BusinessObjectInfo>
    {
        private BusinessObjectInfoList()
        {
            /* Require use of factory methods */
            AllowNew = true;
        }

        #region 获取数据权限列表

        public static BusinessObjectInfoList GetDataPermissionObjectList()
        {
            return DataPortal.Fetch<BusinessObjectInfoList>(true);  //1为区分CSLA的Fetch查找需要的参数
        }

        [RunLocal]
        private void DataPortal_Fetch(bool indataPermission)
        {
            RaiseListChangedEvents = false;

            foreach (var boInfo in ApplicationModel.GetAllEntityInfos())
            {
                if (boInfo.BusinessObjectAttribute.InDataPermission)
                {
                    this.Add(boInfo);
                }
            }

            RaiseListChangedEvents = true;
        }

        #endregion

        #region 获取默认对象列表

        public static BusinessObjectInfoList GetModules()
        {
            return DataPortal.Fetch<BusinessObjectInfoList>();
        }

        [RunLocal]
        private void DataPortal_Fetch()
        {
            RaiseListChangedEvents = false;

            foreach (var item in ApplicationModel.GetAllModules())
            {
                this.Add(item);
            }

            RaiseListChangedEvents = true;
        }

        #endregion

        #region 获取默认对象的聚合对象列表

        /// <summary>
        /// 不包括显示在多对象树中的子对象
        /// </summary>
        /// <param name="rootType"></param>
        /// <returns></returns>
        public static BusinessObjectInfoList GetObjectInfoListInPermission(Type rootType)
        {
            return DataPortal.Fetch<BusinessObjectInfoList>(rootType);
        }

        [RunLocal]
        private void DataPortal_Fetch(Type rootType)
        {
            RaiseListChangedEvents = false;

            BusinessObjectInfo root = ApplicationModel.GetBusinessObjectInfo(rootType);
            AddChildInPermission(this, rootType);

            RaiseListChangedEvents = true;
        }

        private void AddChildInPermission(BusinessObjectInfoList list, Type type)
        {
            var boInfo = ApplicationModel.GetBusinessObjectInfo(type);
            list.Add(boInfo);
            //添加查询对象时
            foreach (var item in boInfo.QueryObjects)
            {
                AddChildInPermission(list, item.ObjectType);
            }
            //根据对象子属性添加
            foreach (var item in ApplicationModel.GetBusinessObjectInfo(type).BOsPropertyInfos)
            {
                if (!item.AssociationAttribute.ShowInTree) //如果显示成树，则子对象不加入
                {
                    AddChildInPermission(list, item.BOType);
                }
            }
            //根据InPermissionAttribute元信息添加
            foreach (var item in ApplicationModel.TypeOwnerInPermission)
            {
                if (item.Value == type)
                {
                    list.Add(ApplicationModel.GetBusinessObjectInfo(item.Key));
                }
            }
        }

        #endregion
    }

    /// <summary>
    /// 业务对象模型
    /// </summary>
    [Serializable]
    [BusinessObject("5947AFB0-96D1-46A3-8134-213ED226F068"), Label("业务对象")]
    [NotAllowEdit]
    public class BusinessObjectInfo : GBusinessBase<BusinessObjectInfo>, IEntityInfo, IEntityViewInfo
    {
        private Guid _id;
        private BusinessObjectInfoList _objectInfoListInPermission;
        private byte[] _backgroudColor;
        private BusinessObjectInfo _parentBoInfo;
        private List<BusinessObjectPropertyInfo> _bOPropertyInfos = new List<BusinessObjectPropertyInfo>();
        private List<BusinessObjectsPropertyInfo> _bOsPropertyInfos = new List<BusinessObjectsPropertyInfo>();
        private List<QueryObjectAttribute> _queryObjects = new List<QueryObjectAttribute>();

        /// <summary>
        /// 构造函数中解析所有类型相关的元数据
        /// </summary>
        /// <param name="boType"></param>
        public BusinessObjectInfo(Type boType)
        {
            this.BOType = boType;
            this.BusinessObjectAttribute = boType.GetSingleAttribute<BusinessObjectAttribute>();
            this._id = new Guid(BusinessObjectAttribute.Id);

            foreach (var item in boType.GetCustomAttributes(typeof(QueryObjectAttribute), false))
            {
                this._queryObjects.Add(item as QueryObjectAttribute);
            }
            //重新排序_queryObjects。
            if (this._queryObjects.Count != 0)
            {
                this._queryObjects = this._queryObjects
                    .OrderBy(c => c.ObjectType.GetSingleAttribute<DefaultObjectAttribute>().Index)
                    .ToList();
            }

            if (String.IsNullOrEmpty(BusinessObjectAttribute.PropertyGroup) == false)
            {
                this.GroupDescriptions = BusinessObjectAttribute.PropertyGroup.Split(';');
            }

            if (boType.HasMarked<DefaultObjectAttribute>())
            {
                this.DefaultObjectAttribute = boType.GetSingleAttribute<DefaultObjectAttribute>();
                this.Index = DefaultObjectAttribute.Index;
            }

            this.NotAllowEdit = boType.HasMarked<NotAllowEditAttribute>();
            this.NotAllowNew = boType.HasMarked<NotAllowNewAttribute>();
            this.NotAllowRemove = boType.HasMarked<NotAllowRemoveAttribute>();

            this._backgroudColor = new byte[4];
            if (boType.HasMarked<BackColorAttribute>())
            {
                this.BackgroundColor = boType.GetSingleAttribute<BackColorAttribute>().Color;
            }

            if (boType.HasMarked<QueryPaneAttribute>())
            {
                this.AutoHideQueryPane = boType.GetSingleAttribute<QueryPaneAttribute>().AutoHide;
            }

            if (boType.HasMarked<LabelAttribute>())
            {
                this.Label = boType.GetSingleAttribute<LabelAttribute>().Label;
            }
            else
            {
                this.Label = boType.Name;
            }

            if (boType.HasMarked<CondtionQueryTypeAttribute>())
            {
                this.ConditionQueryType = boType.GetSingleAttribute<CondtionQueryTypeAttribute>().QueryType;
            }
            if (boType.HasMarked<NavigateQueryTypeAttribute>())
            {
                var attr = boType.GetSingleAttribute<NavigateQueryTypeAttribute>();
                this.NavigateQueryType = attr.QueryType;
                this.NavigateQueryMode = attr.NavigateQueryMode;
                this.NavigateQueryRegionPoistion = attr.NavigateQueryRegionPosition;
            }

            this.LoadPropertiesData(boType);
        }

        [Association(IsRecur = false, CreateToolbar = false)]
        [Label("业务对象")]
        public BusinessObjectInfoList ObjectInfoListInPermission
        {
            get
            {
                if (null == this._objectInfoListInPermission)
                {
                    this._objectInfoListInPermission = BusinessObjectInfoList.GetObjectInfoListInPermission(BOType);
                }
                return this._objectInfoListInPermission;
            }
        }
        public NavigateQueryMode NavigateQueryMode { get; private set; }
        public Guid Id
        {
            get
            {
                return this._id;
            }
        }

        /// <summary>
        /// 自动隐藏查询面板
        /// </summary>
        public bool AutoHideQueryPane { get; set; }

        /// <summary>
        /// 控制显示在模块列表中的顺序
        /// </summary>
        public int Index { get; set; }
        /// <summary>
        /// 默认分组属性值
        /// </summary>
        public string[] GroupDescriptions { get; private set; }
        /// <summary>
        /// 类型名
        /// </summary>
        public string Name
        {
            get
            {
                return BOType.Name;
            }
        }
        /// <summary>
        /// 类别
        /// </summary>
        public string Catalog
        {
            get
            {
                return DefaultObjectAttribute.Catalog;
            }
        }
        /// <summary>
        /// 是否标记了DefaultObjectAttribute
        /// </summary>
        public bool IsDefaultObject
        {
            get
            {
                return null != DefaultObjectAttribute;
            }
        }
        /// <summary>
        /// 拥有的实体属性，即标记了：EntityPropertyAttribute
        /// </summary>
        public IList<BusinessObjectPropertyInfo> BOPropertyInfos
        {
            get
            {
                return this._bOPropertyInfos;
            }
        }

        /// <summary>
        /// 拥有的关联属性，即标记了：AssociationAttribute
        /// </summary>
        public IList<BusinessObjectsPropertyInfo> BOsPropertyInfos
        {
            get
            {
                return this._bOsPropertyInfos;
            }
        }

        [EntityProperty, ShowInList, Label("名称"), IsTitle]
        public string Label { get; private set; }
        /// <summary>
        /// 当前模型是对应这个类型的。
        /// </summary>
        public Type BOType { get; private set; }
        /// <summary>
        /// 标记在CondtionQueryTypeAttribute中的QueryType
        /// </summary>
        public Type ConditionQueryType { get; private set; }
        /// <summary>
        /// 标记在NavigateQueryTypeAttribute中的QueryType
        /// </summary>
        public Type NavigateQueryType { get; private set; }
        public QueryRegionPosition NavigateQueryRegionPoistion { get; private set; }
        public BusinessObjectAttribute BusinessObjectAttribute { get; private set; }
        public DefaultObjectAttribute DefaultObjectAttribute { get; private set; }
        /// <summary>
        /// 获取是否不允许新建
        /// </summary>
        public bool NotAllowNew { get; private set; }
        /// <summary>
        /// 获取是否不允许编辑
        /// </summary>
        public bool NotAllowEdit { get; private set; }
        /// <summary>
        /// 获取是否不允许移除
        /// </summary>
        public bool NotAllowRemove { get; private set; }
        /// <summary>
        /// 直接显示在当前对象下的子对象
        /// </summary>
        public PropertyInfo TreeChildPropertyInfo { get; private set; }
        /// <summary>
        /// AutoUI不满足应用需要时,通过挂接此属性来自定义明细UI
        /// </summary>
        public Type ModuleUIType { get; private set; }
        public Type ListViewUIType { get; private set; }
        public Type DetailViewUIType { get; private set; }
        public IList<QueryObjectAttribute> QueryObjects
        {
            get
            {
                return this._queryObjects;
            }
        }
        public BusinessObjectInfo ParentBoInfo
        {
            get
            {
                return this._parentBoInfo;
            }
            internal set
            {
                this._parentBoInfo = value;
            }
        }
        public BusinessObjectInfo Module
        {
            get
            {
                BusinessObjectInfo result = this;
                while (result._parentBoInfo != null)
                {
                    result = result._parentBoInfo;
                }
                return result;
            }
        }

        public Color BackgroundColor
        {
            get
            {
                return Color.FromArgb(
                    this._backgroudColor[0],
                    this._backgroudColor[1],
                    this._backgroudColor[2],
                    this._backgroudColor[3]
                    );
            }
            private set
            {
                this._backgroudColor[0] = value.A;
                this._backgroudColor[1] = value.R;
                this._backgroudColor[2] = value.G;
                this._backgroudColor[3] = value.B;
            }
        }
        /// <summary>
        /// 直接显示在当前对象下的子对象元数据类型
        /// </summary>
        public BusinessObjectInfo TreeChildBoInfo
        {
            get
            {
                if (null == TreeChildPropertyInfo)
                {
                    return null;
                }
                else
                {
                    return ApplicationModel.GetBusinessObjectInfo(TreeChildPropertyInfo.PropertyType.BaseType.GetGenericArguments()[1]);
                }
            }
        }
        /// <summary>
        /// 显示为标题的属性数据
        /// </summary>
        public BusinessObjectPropertyInfo TitleInfo
        {
            get
            {
                return this.BOPropertyInfos.First(info => info.IsTitle);
            }
        }

        /// <summary>
        /// 根据名字查询实体属性（忽略大小写）
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public BusinessObjectPropertyInfo BOInfoByName(string name)
        {
            return this.BOPropertyInfos.FirstOrDefault(item => item.Name.EqualsIgnorecase(name));
        }
        /// <summary>
        /// 根据名字查询关联属性（忽略大小写）
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public BusinessObjectsPropertyInfo BOsInfoByName(string name)
        {
            return this.BOsPropertyInfos.FirstOrDefault(item => item.Name.EqualsIgnorecase(name));
        }

        public override string ToString()
        {
            return this.Label;
        }

        /// <summary>
        /// 为业务模型对象加入默认不可见命令
        /// </summary>
        /// <param name="bOInfo"></param>
        public void SetDefaultCommands()
        {
            if (NotAllowNew)
            {
                ApplicationModel.AddNotVisibleCommand(CommandNames.Add, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.AddChild, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.CopyAndNew, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.InsertBefore, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.InsertFollow, this);
            }

            if ((TreeChildBoInfo == null)  ||
                ((TreeChildBoInfo != null) && TreeChildBoInfo.NotAllowNew))
                  
            {
                ApplicationModel.AddNotVisibleCommand(CommandNames.AddChildTable, this);
            }

            if (NotAllowRemove)
            {
                ApplicationModel.AddNotVisibleCommand(CommandNames.DeleteChildObject, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.DeleteListObject, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.DeleteBillObject, this);
            }

            if (NotAllowEdit)
            {
                ApplicationModel.AddNotVisibleCommand(CommandNames.MoveDown, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.MoveUp, this);
            }

            if (NotAllowNew && NotAllowRemove && NotAllowEdit)
            {
                ApplicationModel.AddNotVisibleCommand(CommandNames.Cancel, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.Save_Bill, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.Save_List, this);
                ApplicationModel.AddNotVisibleCommand(CommandNames.Refresh, this);
            }
        }

        /// <summary>
        /// 加载所有属性元数据
        /// </summary>
        /// <param name="boType"></param>
        private void LoadPropertiesData(Type boType)
        {
            var properties = boType.GetProperties();
            for (int i = 0, c = properties.Length; i < c; i++)
            {
                var property = properties[i];

                if (property.HasMarked<EntityPropertyAttribute>())
                {
                    this._bOPropertyInfos.Add(new BusinessObjectPropertyInfo(property, this));
                }
                if (property.HasMarked<AssociationAttribute>())
                {
                    var attr = property.GetSingleAttribute<AssociationAttribute>();
                    this._bOsPropertyInfos.Add(new BusinessObjectsPropertyInfo(property, attr, this));
                    if (attr.ShowInTree)
                    {
                        this.TreeChildPropertyInfo = property;
                    }
                }
            }

            this.SortProperties();
        }

        /// <summary>
        /// 把000010000300002排序为000000000000123
        /// 
        /// 不把0的位置改变。
        /// </summary>
        private void SortProperties()
        {
            //这个方法会打乱都是0的节点原有的顺序。
            //this._bOPropertyInfos.Sort((a, b) => a.OrderNo.CompareTo(b.OrderNo));

            var zeroList = this._bOPropertyInfos.Where(p => p.OrderNo == 0).ToArray();
            var list = this._bOPropertyInfos.Where(p => p.OrderNo != 0).OrderBy(p => p.OrderNo).ToArray();
            int i = 0;
            foreach (var item in zeroList)
            {
                this._bOPropertyInfos[i++] = item;
            }
            foreach (var item in list)
            {
                this._bOPropertyInfos[i++] = item;
            }
        }

        #region IEntityInfo Members

        IList<IEntityPropertyInfo> IEntityInfo.BOPropertyInfos
        {
            get
            {
                return this.BOPropertyInfos.ToArray();
            }
        }

        IList<IAssociationPropertyInfo> IEntityInfo.BOsPropertyInfos
        {
            get
            {
                return this.BOsPropertyInfos.ToArray();
            }
        }

        #endregion

        #region IEntityViewInfo Members

        public Type ExtensibleUI
        {
            get
            {
                return this.ModuleUIType;
            }
        }

        IList<string> IEntityViewInfo.GroupDescriptions
        {
            get
            {
                return Array.AsReadOnly(this.GroupDescriptions);
            }
        }

        public IEntityViewInfo EntityInfo
        {
            get
            {
                return this;
            }
        }

        #endregion
    }
}